package controlLayer;

import java.sql.SQLException;
import java.util.List;

import utilLayer.AlreadyExistsException;
import modelLayer.ClassRoom;
import modelLayer.Subject;
import modelLayer.Class;
import modelLayer.Teacher;
import modelLayer.TeachingBlock;
import dbLayer.DBConnection;
import dbLayer.DBTeachingBlock;
import dbLayer.DBTeachingBlockIF;

/**
 * This class is a control layer class of the MSAS system. It functions as the link between 
 * our database and the interface. This class is limited to working with the TeachingBlock class,
 * and whichever other classes class is associated with. There is no direct connection between
 * this class and our database.
 * 
 * @author Danny Mølgaard, Anna Kelemen, Jakob Korsgaard
 * 		   
 * @version 1.3.1
 * 					1.3.1: 		Added more extensive documentation. Verified that
 * 								information contained in the Design Class Diagram,
 * 								is in accordance with the information contained in this
 * 								class.
 *					1.3.2:		Try&catch and throws Exception added to the constructor in order to catch
 *								a NullPointerException and to avoid the program from crashing
 *								if there is no connection to the database. 
 *								getAllByClass() added
 *								removeByClassAndSubject() added
 *								(design class diagram updated)
 */
public class TeachingBlockCtr {
	
	private DBTeachingBlockIF dbTeachingBlock;
	
	/**
	 * Creates an instance of TeachingBlockCtr. Initializes an instance of DBTeachingBlock.
	 * @throws Exception
	 */
	public TeachingBlockCtr() throws Exception{
		try {
			dbTeachingBlock = new DBTeachingBlock();
		}
		catch (Exception e) {
			throw new Exception();
		}
	}
	
	/**
	 * Sends information from the interface on to the database layer, more specifically
	 * helping in the insertion of a new row in the database. Begins a transactions upon
	 * calling the dbLayer method, and rolls it back should anything that could result in dataloss,
	 * or unintended data manipulation occur.
	 * 
	 * @param 		clId	int		the id of the Class associated to the teachingblock
	 * @param 		sId		int	 	the id of the Subject associated to a teachingblock
	 * @param 		crId	int		the id of the ClassRoom associated to a teachingblock
	 * @param 		number	int		number of teachingblocks to be created
	 * @return 		rc		int		the count of rows changed in the database
	 * @throws 				Exception
	 */
	public TeachingBlock createTeachingBlock(int clId, int sId, int crId, int tId, int number) throws Exception {
		
		TeachingBlock tb = null;
		Class cl = new ClassCtr().findClassById(clId, false);
		Subject s = new SubjectCtr().findById(sId, false);
		ClassRoom cr = new ClassRoomCtr().findById(crId);
		Teacher t = new TeacherCtr().findTeacherById(tId);
		
		for (int i = 1; i <= number; ++i){
			tb = new TeachingBlock(cl, s, cr);
			String name = tb.getName();
			try {
				DBConnection.startTransaction();
				dbTeachingBlock.insert(cl, s, cr, t, name);
				DBConnection.commitTransaction();
			}
			catch (SQLException ex) {
				DBConnection.rollbackTransaction();
				throw new AlreadyExistsException(name);
			}
			catch (Exception e) {
				DBConnection.rollbackTransaction();
			}
		}
		
		return tb;
	
	}
	
	/**
	 * Sends information from the interface on to the database layer, more specifically
	 * helping in the search of an existing row in the database.
	 * 
	 * @param 		name				String		the name of the teachingblock
	 * @param 		retrieveAssociation	boolean		determines if we're to retrieve additional information
	 * 												on the teachingblock
	 * @return 							TeachingBlock
	 */
	public TeachingBlock findTeachingBlockByName(String name, boolean retrieveAssociation) {
		
		return dbTeachingBlock.find(name, retrieveAssociation);

	}
	
	/**
	 * Sends information from the interface on to the database layer, more specifically
	 * helping in the search of an existing row in the database.
	 * 
	 * @param 		id					int			the id of the teachingblock
	 * @param 		retrieveAssociation	boolean		determines if we're to retrieve additional information
	 * 												on the teachingblock
	 * @return 							TeachingBlock
	 */
	public TeachingBlock findTeachingBlockById(int id, boolean retrieveAssociation) {

		return dbTeachingBlock.findById(id, retrieveAssociation);

	}
	
	/**
	 * Sends information from the interface on to the database layer, more specifically
	 * helping in the search of all existing rows in the database.
	 * 
	 * @param 		retrieveAssociation	boolean 			determines if we're to retrieve additional information
	 * 														on the teachingblock
	 * @return 							List<TeachingBlock>	a collection of TeachingBlocks
	 */
	public List<TeachingBlock> getAll(boolean retrieveAssociation) {
		
		List<TeachingBlock> list = dbTeachingBlock.getAll(retrieveAssociation);
		return list;
	}
	
	/**
	 * Sends information from the interface on to the database layer, more specifically
	 * helping in the search of all matching rows in the database.
	 * 
	 * @param classId
	 * @param retrieveAssociation
	 * @return a list of matching teachingblocks
	 */
	public List<TeachingBlock> getAllByClass(int classId, boolean retrieveAssociation){
		
		List<TeachingBlock> list = dbTeachingBlock.getAllByClass(classId, retrieveAssociation);
		return list;
	}
	
	/**
	 * Sends information from the interface on to the database layer, more specifically
	 * helping in the renewal of an existing row in the database. Begins a transactions upon
	 * calling the dbLayer method, and rolls it back should anything that could result in data loss,
	 * or unintended data manipulation occur.
	 * 
	 * @param 	tb 	TeachingBlock	an instance of TeachingBlock
	 * @return 	rc	int				the count of rows changed in the database
	 * @throws		Exception
	 */
	public int updateTeachingBlock(TeachingBlock tb) throws Exception {
		
		int rc = -1;
		try {
			DBConnection.startTransaction();
			rc = dbTeachingBlock.update(tb);
			DBConnection.commitTransaction();
		}
		catch (SQLException e) {
			DBConnection.rollbackTransaction();
			throw new AlreadyExistsException(tb.getName());
		}
		catch (Exception e){
			DBConnection.rollbackTransaction();
		}
		
		return rc;
		
	}
	
	/**
	 * Sends information from the interface on to the database layer, more specifically
	 * helping in the removal of an existing row in the database. Begins a transactions upon
	 * calling the dbLayer method, and rolls it back should anything occur that could result in data loss
	 * or unintended data manipulation.
	 * 
	 * @param 	tb 	TeachingBlock	an instance of TeachingBlock
	 * @return 	rc	int 			the count of rows changed in the database.
	 */
	public int removeTeachingBlock(TeachingBlock tb) {
		
		int rc = -1;
		try {
			DBConnection.startTransaction();
			rc = dbTeachingBlock.remove(tb.getId());
			DBConnection.commitTransaction();
		}
		catch (Exception e) {
			DBConnection.rollbackTransaction();
		}
		
		return rc;
		
	}
	
	/**
	 * Sends information from the interface on to the database layer, more specifically
	 * helping in the removal of the matching rows in the database. Begins a transactions upon
	 * calling the dbLayer method, and rolls it back should anything occur that could result in data loss
	 * or unintended data manipulation.
	 * 
	 * @param classId int 
	 * @param subjectId
	 * @return rc - the count of rows changed in the database
	 */
	public int removeByClassAndSubject(int classId, int subjectId) {
		
		int rc = -1;
		try {
			DBConnection.startTransaction();
			rc = dbTeachingBlock.removeByClassAndSubject(classId, subjectId);
			DBConnection.commitTransaction();
		}
		catch (Exception e) {
			DBConnection.rollbackTransaction();
		}
		return rc;
	}
	
}
